﻿using Sidvall.Serialization;

namespace Sidvall.Business
{
    public static class DataPortalManager
    {
        #region Public Members

        #region GetDataPortalException

        public static DataPortalException GetDataPortalException(System.Exception ex, IDataPortalContext context)
        {
            string message;

            if (context != null)
                message = ExceptionHeader + ": " + GetDescription(context);
            else
                message = ExceptionHeader;
            if (ex != null)
                return new DataPortalException(message, ex);
            else
                return new DataPortalException(message);
        }

        #endregion
        #region GetDescription

        public static string GetDescription(IDataPortalContext context)
        {
            if (context == null)
                return string.Empty;
            var message = context.Resource.Append(context.Action, ".").Append(context.ResourceItemId, ".");
            if (!string.IsNullOrWhiteSpace(context.CriteriaId))
                message += " (" + context.CriteriaId + ")";
            return message;
        }

        #endregion

        #region NewContext

        public static DataPortalContext<TResult, TResult> NewContext<TResult>(string resource, string action, string strategyContext, TResult operationContext)
        {
            return NewContext(resource, action, strategyContext, operationContext, operationContext);
        }
        public static DataPortalContext<TResult, TContext> NewContext<TResult, TContext>(string resource, string action, string strategyContext, TContext operationContext,
            TResult resultValue)
        {
            var item = new DataPortalContext<TResult, TContext>(resource, action, operationContext)
            {
                StrategyContext = strategyContext,
                Result = DataPortalResult.None,
                ResultValue = resultValue,
            };
            return item;
        }

        #endregion
        #region NewSaveContext

        public static DataPortalContext<TResult, TResult> NewSaveContext<TResult>(string resource, string action, string strategyContext, TResult operationContext)
        {
            var item = NewContext(resource, action, strategyContext, operationContext, operationContext);
            if (operationContext == null)
                item.Result = DataPortalResult.Skipped;
            return item;
        }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static DataPortalContext<TResult, Sidvall.Data.SaveContext<TResult>> NewSaveContext<TResult>(string resource, string action, string strategyContext,
            Sidvall.Data.SaveContext<TResult> operationContext)
        {
            DataPortalContext<TResult, Sidvall.Data.SaveContext<TResult>> item;

            if ((operationContext != null) && (operationContext.Item != null))
            {
                item = NewContext(resource, action, strategyContext, operationContext, operationContext.Item);
            }
            else
            {
                item = NewContext(resource, action, strategyContext, operationContext, default(TResult));
                item.Result = DataPortalResult.Skipped;
            }

            return item;
        }

        #endregion
        #region NewSaveItemContext

        public static DataPortalContext<TResult, TResult> NewSaveItemContext<TResult>(string resource, string strategyContext,
            TResult operationContext, Sidvall.Data.SaveMode saveMode) where TResult : Sidvall.Data.IDataRowContextProvider
        {
            if (operationContext == null)
                throw new System.ArgumentNullException("operationContext");
            var action = Sidvall.Data.SaveSettings.GetOperationResolved(saveMode, operationContext);
            var item = NewSaveContext(resource, action, strategyContext, operationContext);
            InitializeContext(item, operationContext, saveMode);
            return item;
        }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static DataPortalContext<TResult, Sidvall.Data.SaveContext<TResult>> NewSaveItemContext<TResult>(string resource, string strategyContext,
            Sidvall.Data.SaveContext<TResult> operationContext) where TResult : Sidvall.Data.IDataRowContextProvider
        {
            if (operationContext == null)
                throw new System.ArgumentNullException("operationContext");
            var saveMode = operationContext.GetSaveMode();
            var action = Sidvall.Data.SaveSettings.GetOperationResolved(saveMode, operationContext.Item);
            var item = NewSaveContext(resource, action, strategyContext, operationContext);
            InitializeContext(item, operationContext.Item, saveMode);
            return item;
        }

        #endregion
        #region NewSaveItemsContext

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static DataPortalContext<TResult, Sidvall.Data.SaveContext<Sidvall.Data.IDataRowProvider<TResult>>> NewSaveItemsContext<TResult>(string resource, string strategyContext,
            Sidvall.Data.SaveContext<Sidvall.Data.IDataRowProvider<TResult>> operationContext) where TResult : Sidvall.Data.IDataRowContextProvider
        {
            var item = NewContext(resource, Sidvall.Security.Operations.SaveItems, strategyContext, operationContext, default(TResult));
            if ((operationContext == null) || (operationContext.Item == null))
                item.Result = DataPortalResult.Skipped;
            return item;
        }

        #endregion

        #endregion
        #region Private Members

        private const string ExceptionHeader = "Data Portal Failed";

        #region InitializeContext

        private static void InitializeContext(IDataPortalContext context, Sidvall.Data.IDataRowContextProvider item, Sidvall.Data.SaveMode mode)
        {
            if (!Sidvall.Data.SaveSettings.IsSavable(mode, item))
                context.Result = DataPortalResult.Skipped;
        }

        #endregion

        #endregion
    }
}
